/**
 * Copyright (c) Huawei Technologies Co., Ltd. 2020-2022. All rights reserved.
 */

#include "drv_jpegd.h"
#include "dvpp_cmdlist_num_define.h"
#include "dvpp_tlv_types.h"
#include "drv_jpegd_comm.h"

void drv_jpegd_build_cmdnode(dvpp_decoder *decoder, struct CmdNode *node, uint32_t node_idx)
{
    JpegdConfig *jpegdConfig =
        (JpegdConfig*)(dvpp_get_vpu_mod_val(decoder, node_idx, JPEGD_TLV_TYPE_DEC));

    // 配置cmdnode寄存器
    config_jpegd_cmdnode(node, jpegdConfig);
}

void drv_jpegd_cmdnode_set_next_node(struct CmdBuf *cmd_buf, struct CmdNode *node)
{
    config_jepgd_next_node(cmd_buf, node);
}

void drv_jpegd_cmdnode_set_interrupt(struct CmdNode *node, uint32_t isLastNode)
{
    config_jpegd_interrupt(node, isLastNode);
}

void drv_jpegd_config_sqelist(struct CmdBuf *cmd_buf, uint32_t sqe_idx, uint32_t blkdim)
{
    uint32_t* cur_sqe_addr = (uint32_t*)(uintptr_t)(cmd_buf->bufAddr + sqe_idx * SQE_LEN);
    uint64_t offset =
        (uint64_t)(uintptr_t)(cmd_buf->cmdHeadNode->startAddr) - (uint64_t)(uintptr_t)(cmd_buf->startAddr);
    uint64_t startAddr = cmd_buf->ioStartAddr + offset;

    cur_sqe_addr[NUM_0] = DVPP_SQE_JPEGD; // Type=14 JPEGD任务
    cur_sqe_addr[NUM_0] |= (1 << SQE_WRCQE_OFFSET);
    cur_sqe_addr[NUM_0] |= (blkdim << SQE_BLKDIM_OFFSET); // 第0个4字节的第16-31位表示blockdim的数量
    cur_sqe_addr[NUM_3] &= ~(0xff << SQE_BLKDIM_OFFSET);
    cur_sqe_addr[NUM_3] |= (KERNEL_CREDIT << SQE_TIMEOUT_OFFSET);
    cur_sqe_addr[NUM_3] |= (0x1 << SQE_PTRMODE_OFFSET);
    cur_sqe_addr[NUM_4] = GET_LOW_ADDR((startAddr >> NUM_7));
    cur_sqe_addr[NUM_5] = startAddr >> NUM_39;
    cur_sqe_addr[NUM_6] = cmd_buf->cmdHeadNode->dataSize >> NUM_4;
}

void drv_jpegd_config_sqe(struct CmdBuf *cmd_buf, enum dvpp_sqe_ptr_mode mode, uint32_t blkdim, struct dvpp_sqe *sqe)
{
    if (mode == DVPP_SQE_FIRST_PTR_MODE) {
        uint64_t offset = (uint64_t)(uintptr_t)(cmd_buf->cmdHeadNode->startAddr) -
                          (uint64_t)(uintptr_t)(cmd_buf->startAddr);
        uint64_t startAddr = cmd_buf->ioStartAddr + offset;

        sqe->filed[NUM_0] |= DVPP_SQE_JPEGD;
        sqe->filed[NUM_0] |= (1 << SQE_WRCQE_OFFSET);
        sqe->filed[NUM_3] &= ~(0xff << SQE_BLKDIM_OFFSET);
        sqe->filed[NUM_3] |= (KERNEL_CREDIT << SQE_BLKDIM_OFFSET);
        sqe->filed[NUM_3] &= ~(0x1 << SQE_PTRMODE_OFFSET);
        // Start address [38:7] of the frame (in 128 bytes boundary) for configure buffer.
        sqe->filed[NUM_4] = GET_LOW_ADDR((startAddr >> NUM_7));
        // Start address [63:39] of the frame (in 128 bytes boundary) for configure buffer.
        sqe->filed[NUM_5] = startAddr >> NUM_39;
        sqe->filed[NUM_6] = cmd_buf->cmdHeadNode->dataSize >> NUM_4;
    } else {
        // TD 二级链表模式(多block dim)
        sqe->filed[NUM_0] = DVPP_SQE_JPEGD; // Type=14 JPEGD任务
        sqe->filed[NUM_0] |= (1 << SQE_WRCQE_OFFSET);
        sqe->filed[NUM_0] |= (blkdim << SQE_BLKDIM_OFFSET); // 第0个4字节的第16-31位表示blockdim的数量
        sqe->filed[NUM_3] &= ~(0xff << SQE_BLKDIM_OFFSET);
        sqe->filed[NUM_3] |= (KERNEL_CREDIT << SQE_TIMEOUT_OFFSET); // 第3个4字节的第16-23位表示超时时间
        sqe->filed[NUM_3] |= (0x1 << SQE_PTRMODE_OFFSET); // 第3个4字节的第24位表示链表模式，1表示二级
        sqe->filed[NUM_4] = GET_LOW_ADDR(cmd_buf->ioAddr); // 第4个4字节存放二级链表的低32位地址
        sqe->filed[NUM_5] = GET_HIGH_ADDR(cmd_buf->ioAddr); // 第5个4字节的低16位存放二级链表的高16位地址
        sqe->filed[NUM_5] &= 0x1FFFF; // 第5个4字节的17~30bit是保留字段
        sqe->filed[NUM_5] |= (0x1 << SQE_ADDRTYPE_OFFSET); // 第5个4字节的最高位表示地址类型 1:虚拟地址 0:物理地址
    }
}
